package net.protocol.diameter.dictionary;

/**
 * <pre>
 * <p><b>Default AVPFlagRule:</b>
 *                                       +---------------------+
 *                                       |    AVP Flag rules   |
 *                                       |----+-----+----+-----|----+
 *                   AVP                 |    |     |SHLD| MUST|MAY |
 *   Attribute Name  Code   Data Type    |MUST| MAY | NOT|  NOT|Encr|
 *   ------------------------------------|----+-----+----+-----|----|
 *                                       | M  |  P  |    | V   | N  |
 *   new AVPFlagRule(RLevel.MUST, RLevel.MAY, RLevel.MUSTNOT, false);
 *
 * <p><b>Sample usages:</b>
 *                                       | M  |     |    | P,V | N  |
 *   new AVPFlagRule(RLevel.MUST, RLevel.MUSTNOT, RLevel.MUSTNOT, false);
 * </pre>
 *
 * @author jinhongw@gmail.com
 */
public final class AVPFlagRule {
    public final static RLevel DEFAULT_MANDATORY = RLevel.MUST;
    public final static RLevel DEFAULT_PROTECT = RLevel.MAY;
    public final static RLevel DEFAULT_VENDOR = RLevel.MUSTNOT;
    public final static boolean DEFAULT_ENCRYPT = false;

    private final RLevel mandatory;
    private final RLevel protect;
    private final RLevel vendor;

    private final boolean encrypt;

    public AVPFlagRule() {
        this(DEFAULT_MANDATORY, DEFAULT_PROTECT, DEFAULT_VENDOR,
                DEFAULT_ENCRYPT);
    }

    /**
     * @param mandatory RLevel for AVP Flags 'M' Bit[Mandatory]
     * @param protect   RLevel for AVP Flags 'P' Bit[Protected]
     * @param vendor    RLevel for AVP Flags 'V' Bit[Vendor Specific]
     */
    public AVPFlagRule(RLevel mandatory, RLevel protect, RLevel vendor) {
        this(mandatory, protect, vendor, DEFAULT_ENCRYPT);
    }

    /**
     * @param mandatory RLevel for AVP Flags 'M' Bit[Mandatory]
     * @param protect   RLevel for AVP Flags 'P' Bit[Protected]
     * @param vendor    RLevel for AVP Flags 'V' Bit[Vendor Specific]
     * @param encrypt   If <code>true</code> means may encrypt,<code>false</code> to disable.
     */
    public AVPFlagRule(RLevel mandatory, RLevel protect, RLevel vendor,
                       boolean encrypt) {
        this.mandatory = mandatory;
        this.protect = protect;
        this.vendor = vendor;

        this.encrypt = encrypt;
    }

    public RLevel getMandatory() {
        return mandatory;
    }

    public RLevel getProtect() {
        return protect;
    }

    public RLevel getVendor() {
        return vendor;
    }

    public boolean isEncrypt() {
        return encrypt;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        AVPFlagRule other = (AVPFlagRule) obj;
        if (mandatory != other.mandatory)
            return false;
        if (protect != other.protect)
            return false;
        if (vendor != other.vendor)
            return false;
        if (encrypt != other.encrypt)
            return false;
        return true;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + (encrypt ? 1231 : 1237);
        result = prime * result
                + ((mandatory == null) ? 0 : mandatory.hashCode());
        result = prime * result + ((protect == null) ? 0 : protect.hashCode());
        result = prime * result + ((vendor == null) ? 0 : vendor.hashCode());
        return result;
    }

    @Override
    public String toString() {
        StringBuilder buf = new StringBuilder();
        buf.append(getClass().getSimpleName()).append(" [");
        buf.append("mandatory=").append(mandatory).append(", ");
        buf.append("protect=").append(protect).append(", ");
        buf.append("vendor=").append(vendor).append(", ");
        buf.append("encrypt=").append(encrypt);
        buf.append("]");
        return buf.toString();
    }
}
